import BaseModal, { ModalFC } from '@/components/base/BaseModal';
import { useRequest } from '@/utils/request';
import { Spin, Transfer } from 'antd';
import { difference } from 'lodash-es';
import { useRef, useState } from 'react';
import { getRolePermissions, getTreeRolePermissions, saveRolePermissions } from '../api';
import PermissionTree from '../components/PermissionTree';

const generateTree = (treeNodes: any[] = [], checkedKeys: string[] = []) => {
  const checked: Record<string, unknown>[] = [];
  const unChecked: Record<string, unknown>[] = [];
  treeNodes.forEach(({ children, ...props }) => {
    if (children && children.length > 0) {
      const childs = generateTree(children, checkedKeys);
      if (childs.unChecked.length > 0) {
        unChecked.push({
          ...props,
          children: childs.unChecked
        });
      }
      if (childs.checked.length > 0) {
        checked.push({
          ...props,
          children: childs.checked
        });
      }
    } else if (checkedKeys.includes(props.id)) {
      checked.push({ ...props, children: [] });
    } else {
      unChecked.push({ ...props, children: [] });
    }
  });
  return {
    checked,
    unChecked
  };
};
const BindPermissionModal: ModalFC<{ roleId: string }> = (props) => {
  const { roleId, ...anyProps } = props;
  const [targetKeys, setTargetKeys] = useState<{ operationIds: string[]; permissionIds: string[] }>(
    { permissionIds: [], operationIds: [] }
  );
  const halfKeys = useRef<string[]>([]);
  const tree = useRequest(getTreeRolePermissions);
  useRequest(getRolePermissions, {
    defaultParams: [roleId],
    onSuccess(data) {
      setTargetKeys(data);
    }
  });
  const savePermission = useRequest(saveRolePermissions, {
    manual: true,
    onSuccess() {
      props.onCancel();
    }
  });
  const transferDataSource: any[] = [];
  const buttonList: string[] = [];
  const flatten = (list: Record<string, any>[] = []) => {
    list.forEach((item: any) => {
      transferDataSource.push(item);
      const children = item.operationsList
        ? item.operationsList.map((i: any) => {
            buttonList.push(i.id);
            return { id: i.id, label: i.name };
          })
        : item.permissionTreeVOList;
      flatten(children);
      item.children = children;
    });
  };
  flatten(tree.data || []);
  const checkedKeys = [...targetKeys.operationIds, ...targetKeys.permissionIds];
  return (
    <BaseModal
      title='角色权限绑定'
      width={900}
      {...anyProps}
      onOk={() => {
        const { operationIds, permissionIds } = targetKeys;
        savePermission.run({
          roleId,
          operationIds,
          permissionIds: [...new Set([...permissionIds, ...halfKeys.current])]
        });
      }}
      okButtonProps={{ disabled: tree.loading, loading: savePermission.loading }}
    >
      <Spin spinning={tree.loading}>
        <Transfer
          onChange={(t) => {
            const operationIds: string[] = [];
            const permissionIds: string[] = [];
            t.forEach((i) => {
              if (buttonList.includes(i)) {
                operationIds.push(i);
              } else {
                permissionIds.push(i);
              }
            });
            setTargetKeys({ operationIds, permissionIds });
          }}
          rowKey={(record) => record.id}
          targetKeys={checkedKeys}
          dataSource={transferDataSource}
          render={(item) => item.title}
          showSelectAll={false}
          selectAllLabels={['未绑定权限', '已绑定权限']}
        >
          {({ direction, onItemSelectAll, selectedKeys }) => {
            const { checked, unChecked } = generateTree(tree.data || [], checkedKeys);
            return (
              <PermissionTree
                height={500}
                treeData={direction === 'left' ? unChecked : checked}
                targetKeys={selectedKeys}
                onCheck={(checkedKeys, e) => {
                  halfKeys.current = (e.halfCheckedKeys as string[]) ?? [];
                  const noHasKeys = difference(selectedKeys, checkedKeys as any[]);
                  onItemSelectAll(noHasKeys, false);
                  onItemSelectAll(checkedKeys as any[], true);
                }}
                onSelect={(selected) => {
                  const noHasKeys = difference(selectedKeys, selected as any[]);
                  onItemSelectAll(noHasKeys, false);
                  onItemSelectAll(selected as any[], true);
                }}
              />
            );
          }}
        </Transfer>
      </Spin>
    </BaseModal>
  );
};

export default BindPermissionModal;
